package com.floretexaminaction.timer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.floretexaminaction.model.StudentTestAnswersEntity;
import com.floretexaminaction.redis.Redis;
import com.floretexaminaction.service.UserService;
import org.apache.catalina.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;

import java.text.SimpleDateFormat;
import java.util.*;

public class ThreadTimer {

    Log log = LogFactory.getLog("三岁小仙仙");

    Jedis redis  = Redis.getRedis();

    UserService userService;

    public ThreadTimer(StudentTestAnswersEntity sta, UserService userService,Date endTime){
        Timer timer = new Timer();
        this.userService = userService;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                if(endTime.getTime() <= new Date().getTime()){
                    System.out.println("执行监听 " + sta.getQuestionBank() + " 试题库，线程结束。");
                    // 创建学生作答记录表，并持久化学生作答信息
                    createStudentAnswerBank(sta.getClassNumber(), sta.getQuestionBank());
                    // 计算学生成绩，将学生成绩添加到对应班级内的对应课程中
                    List list = null;
                    list = calcStudentExaminationResult(sta.getClassNumber(), sta.getQuestionBank());
                    if (list!=null){
                        // 创建数据库更新语句，以班级号为表名，课程名为字段，学生成绩为记录，学生学号为条件，执行sql语句
                        String s = redis.get(sta.getClassNumber());
                        JSONArray jsonArray1 = JSONArray.parseArray(s);
                        String coursesName = null;
                        for (int i = 0 ; i  < jsonArray1.size() ; i++){
                            JSONObject jsonObject1 = JSONObject.parseObject(jsonArray1.get(i).toString());
                            if(jsonObject1.get("questionBank").toString().equals(sta.getQuestionBank())){
                                coursesName = jsonObject1.get("coursesName").toString();
                            }
                        }
                        String s1 = userService.saveStudentExaminationResult(sta.getClassNumber(), coursesName, JSON.toJSONString(list));
                        timer.cancel();
                    }
                }else{
                    System.out.println("线程正在执行监听 "+ sta.getQuestionBank() + " 试题库" +
                            "，结束时间：" + sdf.format(endTime) + " 当前时间：" + sdf.format(new Date()));
                }
            }
        }, new Date(), 1000);
    }
    /**
     * 保存学生作答答案信息 -- 创建学生作答记录表
     * @param classNumber 班级号
     * @param questionBank 试题库号
     */
    private void createStudentAnswerBank(String classNumber, String questionBank){
        String tableName = classNumber+"-"+ questionBank;
        String createResult = userService.createStudentAnswerBank(tableName);
        if(createResult.equals("true")){
            String jsonString = redis.get(tableName);
            userService.saveStudentAnswerBank(tableName, jsonString);
        }
    }

    /**
     * 计算一个班级一门考试的学生成绩
     * @param classNumber 班级号
     * @param questionBank 试题库号
     */
    private List calcStudentExaminationResult(String classNumber, String questionBank) {
        // 保存计算出成绩，需要用到的关键信息有：班级号，试题库号，学号，课程名称
        // 1.在学生作答记录表中将所有数据提取为一个数组对象，循环遍历
        // 2.用学生作答记录中的题目id和答案 与 试题库中的id和正确答案相判断
        // 3.在判断过程中，根据分值计算出该学生的成绩
        // 4.计算完成后，再从作答记录表中获取这个成绩对应的学生学号
        // 5.将学生以 {学号:成绩} 对象形式，保存在一个全局的数组中
        // 6.以上 1 到 5 是计算出一个学生的成绩，重复 1 到 5 ，直到所有循环完毕
        // 7.计算出所有学生在本次的考试成绩后，拿方法中的className班级号去缓存中找对应的key
        // 8.在找到的key中，再用questionBank试题库号在班级号里查询考试记录信息，获取本次考试的课程名（科目）
        // 9.执行到了这里，我们拿到了 班级号，课程名，学生对应成绩
        // 10.创建数据库更新语句，以班级号为表名，课程名为字段，学生成绩为记录，学生学号为条件，执行sql语句
        // 完成
        String classNumberQuestionBank = classNumber+"-"+questionBank;
        if(redis.exists(classNumberQuestionBank)){
            String jsonString = redis.get(classNumberQuestionBank);
            return studentResultList(jsonString, questionBank);
        }
        return new ArrayList();
    }

    public List studentResultList(String stu, String questionBank){
        JSONArray jsonArray = JSONArray.parseArray(stu);
        List list = new ArrayList();
        for (int i = 0 ; i < jsonArray.size() ; i++){
            int score = 0;
            JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString());
            JSONArray jsonArray1 = JSONArray.parseArray(jsonObject.get("rightOption").toString());
            for (int j = 0 ; j < jsonArray1.size() ; j++){
                JSONArray jsonArray2 = JSONArray.parseArray(jsonArray1.get(j).toString());
                score += matchingQuestionRightAnswer(questionBank, jsonArray2.get(0).toString(), jsonArray2.get(1).toString());
            }
            StringBuffer sb = new StringBuffer();
            sb.append("['").append(jsonObject.get("studentNumber")).append("','");
            sb.append(score).append("']");
            list.add(sb.toString());
        }
        return list;
    }

    /**
     * 匹配试题库正确答案
     * @param questionNumber 作答试题编号
     * @param answer 作答答案
     * @return true或false
     */
    public int matchingQuestionRightAnswer(String questionBank, String questionNumber, String answer){
        // 获取试题库正确答案的方法有两种，一是：从数据库获取，二是：从缓存中获取
        // 判断，若缓存中不存在该试题库，则从数据库中获取
        String jsonString = null;
        if(redis.exists(questionBank)){
            jsonString = redis.get(questionBank);
        }else{
            jsonString = userService.queryClassStuFindNumber(questionBank);
        }
        JSONArray jsonArray = JSONArray.parseArray(jsonString);
        for (int i = 0 ; i < jsonArray.size() ; i++){
            JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString());
            if(jsonObject.get("id").toString().equals(questionNumber) && jsonObject.get("rightOption").toString().equals(answer)){
                return Integer.valueOf(jsonObject.get("score").toString());
            };
        }
        return 0;
    }
}
